package org.cbioportal.legacy.persistence.mybatis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.cbioportal.legacy.model.CancerStudy;
import org.cbioportal.legacy.model.Patient;
import org.cbioportal.legacy.model.Sample;
import org.cbioportal.legacy.model.meta.BaseMeta;
import org.cbioportal.legacy.persistence.mybatis.config.TestConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {SampleMyBatisRepository.class, TestConfig.class})
public class SampleMyBatisRepositoryTest {

  @Autowired private SampleMyBatisRepository sampleMyBatisRepository;

  @Test
  public void getAllSamplesInStudyIdProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesInStudy(
            "study_tcga_pub", "ID", null, null, null, null);

    Assert.assertEquals(15, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertNull(sample.getPatient());
  }

  @Test
  public void getAllSamplesInStudySummaryProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesInStudy(
            "study_tcga_pub", "SUMMARY", null, null, null, null);

    Assert.assertEquals(15, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 1, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId());
    Assert.assertNull(sample.getPatient());
  }

  @Test
  public void getAllSamplesInStudyDetailedProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesInStudy(
            "study_tcga_pub", "DETAILED", null, null, null, null);

    Assert.assertEquals(15, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 1, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId());
    Patient patient = sample.getPatient();
    Assert.assertEquals((Integer) 1, patient.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId());
    Assert.assertEquals((Integer) 1, patient.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier());
    CancerStudy cancerStudy = patient.getCancerStudy();
    Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier());
    Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId());
    Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName());
    Assert.assertEquals(
        "<a href=\\\"http://cancergenome.nih.gov/\\\">The Cancer Genome Atlas (TCGA)</a> Breast"
            + " Invasive Carcinoma project. 825 cases.<br><i>Nature 2012.</i> <a href=\\\"http://tcga-data.nci."
            + "nih.gov/tcga/\\\">Raw data via the TCGA Data Portal</a>.",
        cancerStudy.getDescription());
    Assert.assertEquals(true, cancerStudy.getPublicStudy());
    Assert.assertEquals("23000897,26451490", cancerStudy.getPmid());
    Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation());
    Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups());
    Assert.assertEquals((Integer) 0, cancerStudy.getStatus());
  }

  @Test
  public void getAllSamplesInStudySummaryProjection1PageSize() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesInStudy("study_tcga_pub", "SUMMARY", 1, 0, null, null);

    Assert.assertEquals(1, result.size());
  }

  @Test
  public void getAllSamplesInStudySummaryProjectionStableIdSort() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesInStudy(
            "study_tcga_pub", "SUMMARY", null, null, "stableId", "ASC");

    Assert.assertEquals(15, result.size());
    Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId());
    Assert.assertEquals("TCGA-A1-A0SB-02", result.get(1).getStableId());
    Assert.assertEquals("TCGA-A1-A0SD-01", result.get(2).getStableId());
    Assert.assertEquals("TCGA-A1-A0SE-01", result.get(3).getStableId());
    Assert.assertEquals("TCGA-A1-A0SF-01", result.get(4).getStableId());
    Assert.assertEquals("TCGA-A1-A0SG-01", result.get(5).getStableId());
  }

  @Test
  public void getMetaSamplesInStudy() throws Exception {

    BaseMeta result = sampleMyBatisRepository.getMetaSamplesInStudy("study_tcga_pub");

    Assert.assertEquals((Integer) 15, result.getTotalCount());
  }

  @Test
  public void getSampleInStudyNullResult() throws Exception {

    Sample result = sampleMyBatisRepository.getSampleInStudy("study_tcga_pub", "invalid_sample");

    Assert.assertNull(result);
  }

  @Test
  public void getSampleInStudy() throws Exception {

    Sample sample = sampleMyBatisRepository.getSampleInStudy("study_tcga_pub", "TCGA-A1-A0SI-01");

    Assert.assertEquals((Integer) 7, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SI-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 7, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SI", sample.getPatientStableId());
    Patient patient = sample.getPatient();
    Assert.assertEquals((Integer) 7, patient.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SI", patient.getStableId());
    Assert.assertEquals((Integer) 1, patient.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier());
    CancerStudy cancerStudy = patient.getCancerStudy();
    Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier());
    Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId());
    Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName());
    Assert.assertEquals(
        "<a href=\\\"http://cancergenome.nih.gov/\\\">The Cancer Genome Atlas (TCGA)</a> Breast"
            + " Invasive Carcinoma project. 825 cases.<br><i>Nature 2012.</i> <a href=\\\"http://tcga-data.nci."
            + "nih.gov/tcga/\\\">Raw data via the TCGA Data Portal</a>.",
        cancerStudy.getDescription());
    Assert.assertEquals(true, cancerStudy.getPublicStudy());
    Assert.assertEquals("23000897,26451490", cancerStudy.getPmid());
    Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation());
    Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups());
    Assert.assertEquals((Integer) 0, cancerStudy.getStatus());
  }

  @Test
  public void getAllSamplesOfPatientInStudyIdProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientInStudy(
            "study_tcga_pub", "TCGA-A1-A0SB", "ID", null, null, null, null);

    Assert.assertEquals(2, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertNull(sample.getPatient());
  }

  @Test
  public void getAllSamplesOfPatientInStudySummaryProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientInStudy(
            "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, null, null);

    Assert.assertEquals(2, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 1, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId());
    Assert.assertNull(sample.getPatient());
  }

  @Test
  public void getAllSamplesOfPatientInStudyDetailedProjection() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientInStudy(
            "study_tcga_pub", "TCGA-A1-A0SB", "DETAILED", null, null, null, null);

    Assert.assertEquals(2, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 1, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId());
    Patient patient = sample.getPatient();
    Assert.assertEquals((Integer) 1, patient.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB", patient.getStableId());
    Assert.assertEquals((Integer) 1, patient.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", patient.getCancerStudyIdentifier());
    CancerStudy cancerStudy = patient.getCancerStudy();
    Assert.assertEquals((Integer) 1, cancerStudy.getCancerStudyId());
    Assert.assertEquals("study_tcga_pub", cancerStudy.getCancerStudyIdentifier());
    Assert.assertEquals("brca", cancerStudy.getTypeOfCancerId());
    Assert.assertEquals("Breast Invasive Carcinoma (TCGA, Nature 2012)", cancerStudy.getName());
    Assert.assertEquals(
        "<a href=\\\"http://cancergenome.nih.gov/\\\">The Cancer Genome Atlas (TCGA)</a> Breast"
            + " Invasive Carcinoma project. 825 cases.<br><i>Nature 2012.</i> <a href=\\\"http://tcga-data.nci."
            + "nih.gov/tcga/\\\">Raw data via the TCGA Data Portal</a>.",
        cancerStudy.getDescription());
    Assert.assertEquals(true, cancerStudy.getPublicStudy());
    Assert.assertEquals("23000897,26451490", cancerStudy.getPmid());
    Assert.assertEquals("TCGA, Nature 2012, ...", cancerStudy.getCitation());
    Assert.assertEquals("SU2C-PI3K;PUBLIC;GDAC", cancerStudy.getGroups());
    Assert.assertEquals((Integer) 0, cancerStudy.getStatus());
  }

  @Test
  public void getAllSamplesOfPatientInStudySummaryProjection1PageSize() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientInStudy(
            "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", 1, 0, null, null);

    Assert.assertEquals(1, result.size());
  }

  @Test
  public void getAllSamplesOfPatientInStudySummaryProjectionStableIdSort() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientInStudy(
            "study_tcga_pub", "TCGA-A1-A0SB", "SUMMARY", null, null, "stableId", "ASC");

    Assert.assertEquals(2, result.size());
    Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId());
    Assert.assertEquals("TCGA-A1-A0SB-02", result.get(1).getStableId());
  }

  @Test
  public void getMetaSamplesOfPatientInStudy() throws Exception {

    BaseMeta result =
        sampleMyBatisRepository.getMetaSamplesOfPatientInStudy("study_tcga_pub", "TCGA-A1-A0SB");

    Assert.assertEquals((Integer) 2, result.getTotalCount());
  }

  @Test
  public void getAllSamplesOfPatientsInStudy() throws Exception {

    List<Sample> result =
        sampleMyBatisRepository.getAllSamplesOfPatientsInStudy(
            "study_tcga_pub", Arrays.asList("TCGA-A1-A0SB", "TCGA-A1-A0SE"), "SUMMARY");

    Assert.assertEquals(3, result.size());
    Sample sample = result.get(0);
    Assert.assertEquals((Integer) 1, sample.getInternalId());
    Assert.assertEquals("TCGA-A1-A0SB-01", sample.getStableId());
    Assert.assertEquals(Sample.SampleType.PRIMARY_SOLID_TUMOR, sample.getSampleType());
    Assert.assertEquals((Integer) 1, sample.getPatientId());
    Assert.assertEquals("TCGA-A1-A0SB", sample.getPatientStableId());
    Assert.assertNull(sample.getPatient());
  }

  @Test
  public void fetchSamples() throws Exception {

    List<String> studyIds = new ArrayList<>();
    studyIds.add("study_tcga_pub");
    studyIds.add("study_tcga_pub");
    List<String> sampleIds = new ArrayList<>();
    sampleIds.add("TCGA-A1-A0SB-01");
    sampleIds.add("TCGA-A1-A0SE-01");

    List<Sample> result = sampleMyBatisRepository.fetchSamples(studyIds, sampleIds, "SUMMARY");

    Assert.assertEquals(2, result.size());
    Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId());
    Assert.assertEquals("TCGA-A1-A0SE-01", result.get(1).getStableId());
  }

  @Test
  public void fetchSamplesBySampleListId() throws Exception {

    List<String> sampleListIds = new ArrayList<>();
    sampleListIds.add("study_tcga_pub_all");
    sampleListIds.add("study_tcga_pub_acgh");

    List<Sample> result =
        sampleMyBatisRepository.fetchSamplesBySampleListIds(sampleListIds, "SUMMARY");

    Assert.assertEquals(14, result.size());
    Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId());
    Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1).getStableId());
    Assert.assertEquals("TCGA-A1-A0SE-01", result.get(2).getStableId());
    Assert.assertEquals("TCGA-A1-A0SF-01", result.get(3).getStableId());
    Assert.assertEquals("TCGA-A1-A0SG-01", result.get(4).getStableId());
    Assert.assertEquals("TCGA-A1-A0SH-01", result.get(5).getStableId());
  }

  @Test
  public void fetchMetaSamples() throws Exception {

    List<String> studyIds = new ArrayList<>();
    studyIds.add("study_tcga_pub");
    studyIds.add("study_tcga_pub");
    List<String> sampleIds = new ArrayList<>();
    sampleIds.add("TCGA-A1-A0SB-01");
    sampleIds.add("TCGA-A1-A0SE-01");

    BaseMeta result = sampleMyBatisRepository.fetchMetaSamples(studyIds, sampleIds);

    Assert.assertEquals((Integer) 2, result.getTotalCount());
  }

  @Test
  public void fetchMetaSamplesBySampleListId() throws Exception {

    List<String> sampleListIds = new ArrayList<>();
    sampleListIds.add("study_tcga_pub_all");
    sampleListIds.add("study_tcga_pub_acgh");

    BaseMeta result = sampleMyBatisRepository.fetchMetaSamples(sampleListIds);

    Assert.assertEquals((Integer) 14, result.getTotalCount());
  }

  @Test
  public void getSamplesByInternalIds() throws Exception {

    List<Sample> result = sampleMyBatisRepository.getSamplesByInternalIds(Arrays.asList(1, 2));

    Assert.assertEquals(2, result.size());
    Assert.assertEquals("TCGA-A1-A0SB-01", result.get(0).getStableId());
    Assert.assertEquals("TCGA-A1-A0SD-01", result.get(1).getStableId());
  }

  @Test
  public void getSamplesByKeyword() {
    List<Sample> result =
        sampleMyBatisRepository.getAllSamples("TCGA-A1-A0SB", null, "SUMMARY", 10, 0, null, null);
    List<String> actual = result.stream().map((Sample::getStableId)).collect(Collectors.toList());
    List<String> expected = Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-A0SB-01", "TCGA-A1-A0SB-02");

    Assert.assertEquals(expected, actual);
  }

  @Test
  public void getSamplesByEmptyKeyword() {
    List<Sample> result =
        sampleMyBatisRepository.getAllSamples(" ", null, "SUMMARY", 10, 0, null, null);
    List<String> actual = result.stream().map((Sample::getStableId)).collect(Collectors.toList());
    List<String> expected =
        Arrays.asList(
            "TCGA-A1-A0SB-01",
            "TCGA-A1-A0SB-01",
            "TCGA-A1-A0SB-02",
            "TCGA-A1-A0SD-01",
            "TCGA-A1-A0SE-01",
            "TCGA-A1-A0SF-01",
            "TCGA-A1-A0SG-01",
            "TCGA-A1-A0SH-01",
            "TCGA-A1-A0SI-01",
            "TCGA-A1-A0SJ-01");

    Assert.assertEquals(expected, actual);
  }

  @Test
  public void getSamplesByKeywordFilterByStudies() {
    List<Sample> result =
        sampleMyBatisRepository.getAllSamples(
            "TCGA-A1", Collections.singletonList("acc_tcga"), "SUMMARY", 10, 0, null, null);
    List<String> actual = result.stream().map(Sample::getStableId).collect(Collectors.toList());
    List<String> expected =
        Arrays.asList("TCGA-A1-A0SB-01", "TCGA-A1-B0SO-01", "TCGA-A1-B0SP-01", "TCGA-A1-B0SQ-01");

    Assert.assertEquals(expected, actual);
  }

  @Test
  public void getSamplesByKeywordFilterByNoStudies() {
    List<Sample> result =
        sampleMyBatisRepository.getAllSamples(
            "TCGA-A1", new ArrayList<>(), "SUMMARY", 10, 0, null, null);
    List<String> actual = result.stream().map(Sample::getStableId).collect(Collectors.toList());
    List<String> expected = Collections.emptyList();

    Assert.assertEquals(expected, actual);
  }

  @Test
  public void getMetaSamplesByKeyword() {
    BaseMeta actual = sampleMyBatisRepository.getMetaSamples("TCGA-A1-A0SB", null);
    Integer expected = 3;

    Assert.assertEquals(expected, actual.getTotalCount());
  }
}
